#if !defined(ximera_net_address_hpp)
#define ximera_net_address_hpp

// -----------------------------------------------------------

#include <ximera/types.hpp>
#include <ximera/enum.hpp>

namespace ximera { namespace net
{
    XIMERA_ENUM(IPVersion)
        Unknown,
        IPv4,
        IPv6
    XIMERA_ENUM_END(IPVersion)

    class XIMERA_API IPAddress
    {
    public:
        static IPAddress any;

    public:
        IPAddress();
        explicit IPAddress(String const& ip);
        IPAddress(String const& ip, IPVersion version);

        String toString() const;
        UInt32 toInt() const;

        IPVersion version() const;

        bool operator==(IPAddress const& rhs) const;

    private:
        UInt32 _addressV4;
        IPVersion _version;

        void parse(String const& ip);
    };

    inline std::wostream& operator<<(std::wostream& os, IPAddress const& rhs)
    {
        return os << rhs.toString();
    }

    typedef Int32 Port;

    class XIMERA_API IPEndPoint
    {
    public:
        IPEndPoint();
        IPEndPoint(IPAddress const& address, Port port);
        IPEndPoint(IPAddress const& address, String const& service);
        IPEndPoint(String const& host, Port port);
        IPEndPoint(String const& host, String const& service);

        IPAddress const& address() const;
        void address(IPAddress const& value);

        Port const& port() const;
        void port(Port const& value);

        bool operator==(IPEndPoint const& rhs) const;

    private:
        IPAddress _address;
        Port _port;

        Port getPort(String const& service) const;
        IPAddress getAddress(String const& host) const;
    };

    inline std::wostream& operator<<(std::wostream& os, IPEndPoint const& rhs)
    {
        return os << rhs.address() << ":" << rhs.port();
    }
}}

// -----------------------------------------------------------

#endif
